package com.shrw.duke.serialport.utils;

import com.shrw.duke.serialport.common.PortArg;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidParameterException;

import serial.utils.SerialPort;

/**
 * Created by rw-duke on 2018/4/2.
 */

public class PortUtils {
    private static PortUtils instance;

    private SerialPort mSerialPort;

    private PortUtils() {
        this.mSerialPort = new SerialPort();
    }

    public static PortUtils getInstance() {
        if (instance == null) {
            synchronized (PortUtils.class) {
                if (instance == null) {
                    instance = new PortUtils();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化串口
     *
     * @param device
     * @param baudrate
     * @param nBits
     * @param nEvent
     * @param nStop
     * @param flags
     * @throws SecurityException 串口初始化异常
     */
    public void initPort(String device, int baudrate, int nBits, char nEvent,
                         int nStop, int flags) throws SecurityException {
        if ((device.length() == 0) || (baudrate == -1) || nBits == -1
                || nStop == -1 || nEvent == 'C') {
            throw new InvalidParameterException();
        }
        File devices = new File(device);
        if (!devices.canRead() || !devices.canWrite()) {
            try {
                /**
                 Missing read/write permission, trying to chmod the file
                 */
                Process su;
                su = Runtime.getRuntime().exec("/system/bin/su");
                String cmd = "chmod 666 " + devices.getAbsolutePath() + "\n"
                        + "exit\n";
                su.getOutputStream().write(cmd.getBytes());
                if ((su.waitFor() != 0) || !devices.canRead()
                        || !devices.canWrite()) {
                    throw new SecurityException(cmd + " open returns null");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new SecurityException("open returns null");
            }

        }
    }

    /**
     * 串口电源打开或者关闭
     *
     * @param isUpPower true：打开； false：关闭
     */
    public void upOrDownPower(boolean isUpPower) {
        if (isUpPower) {
            //up power
            SerialPort.SetIoState(PortArg.IOCTRL_PMU_BARCODE_ON);
            SerialPort.SetIoState(PortArg.IOCTRL_PMU_RFID_ON);
        } else {
            //down power
            SerialPort.SetIoState(PortArg.IOCTRL_PMU_BARCODE_OFF);
            SerialPort.SetIoState(PortArg.IOCTRL_PMU_RFID_OFF);
        }

    }

    /**
     *  打开串口
     *
     * @throws IOException 串口打开异常
     * @throws InvalidParameterException 串口初始化异常
     * @return 用来获取文件流发送接收数据
     */
    public FileDescriptor open() throws IOException, InvalidParameterException {
        String path = PortArg.device;
        int baudrate = Integer.decode(PortArg.baudrate);
        int nbits = Integer.decode(PortArg.bits);
        int nstop = Integer.decode(PortArg.nstop);
        char cVerify = PortArg.cverify.charAt(0);
        return open(new File(path),baudrate,nbits,cVerify,nstop,0);
    }

    public FileDescriptor open(File device, int baudrate, int nBits, char nEvent,
                               int nStop, int flags)throws IOException,InvalidParameterException{

        if ((device.getAbsolutePath().length() == 0) || (baudrate == -1) || nBits == -1
                || nStop == -1 || nEvent == 'C') {
            throw new InvalidParameterException("串口参数异常");
        }
        if (!device.canRead() || !device.canWrite()) {
            try {
                /**
                 Missing read/write permission, trying to chmod the file
                 */
                Process su;
                su = Runtime.getRuntime().exec("/system/bin/su");
                String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
                        + "exit\n";
                su.getOutputStream().write(cmd.getBytes());
                if ((su.waitFor() != 0) || !device.canRead()
                        || !device.canWrite()) {
                    throw new SecurityException(cmd + " open returns null");
                }

            } catch (Exception e) {
                e.printStackTrace();
                throw new SecurityException("open returns null");
            }

        }

        FileDescriptor fd = mSerialPort.open(device, baudrate, nBits, nEvent, nStop, flags);
        if (fd == null) {
//            Log.e(TAG, "native open returns null");
            throw new IOException("native open returns null");
        }
        return fd;

    }

    /**
     * 关闭串口
     */
    public void close(){
        if (mSerialPort!=null){
            mSerialPort.close();
        }
    }

    /**
     * 输入流读取数据
     * @param fd
     * @return
     */
    public FileInputStream getFileInputStream(FileDescriptor fd){
        return new FileInputStream(fd);
    }

    /**
     * 输出流发送据
     * @param fd
     * @return
     */
    public FileOutputStream getFileOutputStream(FileDescriptor fd){
        return new FileOutputStream(fd);
    }




}
